<?php

namespace App\Logic\Member;

use App\Component\DeviceIdentity\DeviceUser;
use App\Component\User;
use App\Component\LogListForm;
use App\Core\BaseCore;
use App\Core\Exception\DefaultException;
use App\Core\Exception\ValidationException;
use App\Core\Output;
use App\Enums\ValidateEnums;
use App\Event\Event;
use App\EventHandler\CountUserHandler;
use App\Logic\Member\Form\MemberListForm;
use App\Logic\Member\Form\ScoreListForm;
use App\Logic\Order\OrderService;
use App\Model\Member\MemberModel;
use App\Model\Member\MemberProfitScoreModel;
use App\Model\Member\MemberProfitStatisticsModel;
use App\Model\Order\OrderModel;
use App\Model\UserModel;
use App\Util\ArrayHelper;
use App\Util\CommonHelper;
use App\Util\UserIdentityHelper;
use EasySwoole\Component\Di;
use EasySwoole\Component\Singleton;
use EasySwoole\EasySwoole\Config as ESConfig;
use EasySwoole\Http\Request;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Redis\Redis;
use EasySwoole\RedisPool\RedisPool;
use EasySwoole\Utility\Random;
use EasySwoole\Validate\Validate;
use Throwable;

class MemberService extends BaseCore
{

    use Singleton;

    /**
     * 生成密码&密码种子
     * @param $password
     * @return array [密码,密码种子]
     */
    public function getPassword($password)
    {
        $salt = \EasySwoole\Utility\Random::character(9);
        $pwd = CommonHelper::pwdEncrypt($password, $salt);
        return [$pwd, $salt];
    }

    /**
     * 字典数据
     * @param $data
     * @return Output
     * @throws Exception
     * @throws Throwable
     */
    public function getDict(Request $request) : Output
    {


        $result = [
            'state_list'          => ArrayHelper::keyArrayToList(MemberModel::getStateDict()),
        ];

        return $this->success($result);
    }

    /**
     * 登陆操作 login
     * @param $username
     * @param $password
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     */
    public function login($username, $password)
    {
        /** @var User $device */
        $device = Di::getInstance()->get('user');

        if ($device->isLogin()) {
            return $this->success();
        }

        /** @var Redis $cache */
        $cache      = RedisPool::defer();
        $cache_key  = "userError:" . $username;
        $cache_data = $cache->get($cache_key);
        if (!empty($cache_data) && $cache_data > 3) { //缓存存在
            throw new DefaultException('密码不正确');
        }
        $deviceIdentity = DeviceUser::findIdentityByUsername($username, $password);


        $device->login($deviceIdentity);
        //放回前端需要的数据
        $return = [
            'userid'                => $deviceIdentity->getUserId(),
            'username'              => $deviceIdentity->getUsername(),
//            'phone'      => $deviceIdentity->getPhone(),
            'name'                  => $deviceIdentity->getName(),
            'referrer_id'           => $deviceIdentity->getReferrerID(),
            'usdt'                  => $deviceIdentity->getUsdt(),
            'alipay_qr'             => $deviceIdentity->getAlipayQr(),
            'wechat_qr'             => $deviceIdentity->getWepayQr(),
            'pub_bank_name'         => $deviceIdentity->getPubBankName(),
            'pub_bank_deposit'      => $deviceIdentity->getPubBankDeposit(),
            'pub_bank_account_name' => $deviceIdentity->getPubBankAccountName(),
            'pub_bank_account_no'   => $deviceIdentity->getPubBankAccountNo(),
            'pri_bank_name'         => $deviceIdentity->getPriBankName(),
            'pri_bank_deposit'      => $deviceIdentity->getPriBankDeposit(),
            'pri_bank_account_name' => $deviceIdentity->getPriBankAccountName(),
            'pri_bank_account_no'   => $deviceIdentity->getPriBankAccountNo(),
            'score'                 => $deviceIdentity->getScore(),
            'profit_score'          => $deviceIdentity->getProfitScore(),
            'profit'                => $deviceIdentity->getProfit(),
            'avatar'                => '../../static/home/tab_me_s.png'
        ];

        //更新最后登录时间
        MemberModel::updateData(['last_login_time' => CommonHelper::currentTime()], ['id' => $deviceIdentity->getUserId()]);

        return $this->success($return);
    }

    public function info(Request $request)
    {
        /** @var User $device */
        $device         = Di::getInstance()->get('user');
        $deviceIdentity = $device->getIdentity();
        $return         = [
            'userid'                 => $deviceIdentity->getId(),
            'username'               => $deviceIdentity->getUsername(),
            'name'                   => $deviceIdentity->getName(),
            'referrer_id'            => $deviceIdentity->getReferrerID(),
            'usdt'                   => $deviceIdentity->getUsdt(),
            'binance'                   => $deviceIdentity->binance,
            'trx'                   => $deviceIdentity->trx,
            'alipay_qr'              => $deviceIdentity->getAlipayQr(),
            'wechat_qr'              => $deviceIdentity->getWepayQr(),
            'pub_bank_name'          => $deviceIdentity->getPubBankName(),
            'pub_bank_deposit'       => $deviceIdentity->getPubBankDeposit(),
            'pub_bank_account_name'  => $deviceIdentity->getPubBankAccountName(),
            'pub_bank_account_no'    => $deviceIdentity->getPubBankAccountNo(),
            'pri_bank_name'          => $deviceIdentity->getPriBankName(),
            'pri_bank_deposit'       => $deviceIdentity->getPriBankDeposit(),
            'pri_bank_account_name'  => $deviceIdentity->getPriBankAccountName(),
            'pri_bank_account_no'    => $deviceIdentity->getPriBankAccountNo(),
            'score'                  => $deviceIdentity->getScore(),
            'profit_score'           => $deviceIdentity->getProfitScore(),
            'profit'                 => $deviceIdentity->getProfit(),//收益率
            'avatar'                 => '../../static/home/tab_me_s.png',
            'order_count'            => $deviceIdentity->order_count,
            'next_user_profit'      => bcmul($deviceIdentity->getScore(), $deviceIdentity->getProfit()/100, 2),//预估收益
            'next_user_profit_time'  => strtotime($deviceIdentity->last_profit_time) < 0 ? date('Y-m-d 00:00:15', time() + 86400) : date('Y-m-d H:i:s', strtotime($deviceIdentity->last_profit_time) + 86400),//预估收益时间
            'today_user_profit'      => $deviceIdentity->today_user_profit,//今日个人收益
            'today_referrer_profit'  => $deviceIdentity->today_referrer_profit,//今日团队收益
            'user_profit_amount'     => $deviceIdentity->user_profit_amount,//个人收益总金额数
            'referrer_profit_amount' => $deviceIdentity->referrer_profit_amount,//团队收益总金额数
            'total_profit_amount'    => bcadd($deviceIdentity->referrer_profit_amount, $deviceIdentity->user_profit_amount, 2),//收益总金额数
            'subordinate_count'      => $deviceIdentity->subordinate_count,//团队总人数
            'subordinate_score'      => $deviceIdentity->subordinate_score,//下级账户总额
            'last_count_time'        => $deviceIdentity->last_count_time,//最后统计时间
            'today_count'            => (date('Y-m-d', strtotime($deviceIdentity->last_count_time)) == date('Y-m-d')) ? 1 : 0,//最后统计时间是否为今天
        ];
        /**订单统计 总订单/已完结订单提成/未完结订单总数/未完结订单提成*/
//        $orderStatistics                  = OrderService::getInstance()->statistics($request)->getData();
//        $return['order_count']            = $orderStatistics['order_count'];
//        $return['finished_user_profit']   = $orderStatistics['finished_user_profit'];
//        $return['unfinished_order_count'] = $orderStatistics['unfinished_order_count'];
//        $return['unfinished_order_amount'] = $orderStatistics['unfinished_order_amount'];
//        $return['unfinished_user_profit'] = $orderStatistics['unfinished_user_profit'];
//        $return['unfinished_referrer_profit'] = $orderStatistics['unfinished_referrer_profit'];

        return $this->success($return);
    }

    /**
     * 创建用户
     * @param string $phone 手机号码
     * @param string $password 明文密码
     * @param string $device_id 设备id
     * @param string $device_name 设备名称
     */
    public function createUser($data)
    {
        // 验证规则
        $rules = [
            'username'       => 'required|notEmpty|lengthMin:5|lengthMax:20',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
            'repassword'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
            'referrer_id'   => 'required|notEmpty',
        ];

        // 验证字段的别名
        $alias = [
            'username'       => '用户名',
            'password'    => '密码',
            'repassword'    => '确认密码',
            'referrer_id'   => '推荐码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        if($data['password'] <> $data['repassword']){
            throw new ValidationException(ValidateEnums::CHECK_REQUIRED, '两次输入密码不一致');
        }
        $username       = $data['username'];
        $password    = $data['password'];
        $referrer_id   = $data['referrer_id'];

        if (MemberModel::getCount(['username' => $username]) != 0) {
            throw new ValidationException(ValidateEnums::CHECK_REQUIRED, '该用户名号已经注册');
        }

        //生成账户密码
        list($password, $salt) = self::getPassword($data['password']);

        //推荐人id referrer_id;
        if ($referrer_id > 0) {
            if (MemberModel::getCount(['id' => $referrer_id]) == 0) {
                throw new DefaultException('推荐码错误！');
            }
        }else{
            throw new DefaultException('推荐码错误！');
        }
        DbManager::getInstance()->startTransactionWithCount('write');
        try {

            $res     = (new MemberModel())->createUser($username, $password, $salt, $referrer_id);
            $user_id = $res->lastQueryResult()->getLastInsertId();

            //注册送免费VIP
//            Event::getInstance()->hook(
//                Event::EVENT_FREE_VIP_EXPIRE,
//                [
//                    'user_id'  => $user_id
//                ]
//            );
//            //注册更新推荐表数据
//            Event::getInstance()->hook(
//                Event::EVENT_REFERRER_MEMBER,
//                [
//                    'user_id'  => $user_id,
//                    'referrer_id'  => $referrer_id,
//                ]
//            );

            DbManager::getInstance()->commitWithCount('write');

            /**注册完成之后自动登录*/
            return $this->login($username, $data['password']);

        } catch (\Throwable $e) {
            DbManager::getInstance()->rollbackWithCount('write');
            throw new DefaultException($e->getMessage());
        }
    }

    /**
     * 会员列表 getLists
     * @param Request $request
     * @return Output
     * @throws Throwable
     * @throws \EasySwoole\Redis\Exception\RedisException
     */
    public function getLists(Request $request):Output
    {
        $params = $request->getQueryParams();
        /** @var Redis $cache */
        $cache     = Di::getInstance()->get("REDIS");
        $cache_key = "memberCache:list:" . json_encode($params + ['_id' => UserIdentityHelper::getId(), '_name' => UserIdentityHelper::getUsername()]);
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $data = json_decode($cache_data, true);
        } else {
            $form = new MemberListForm($params, $request);
            $data = $form->lists();
            $cache->set($cache_key, json_encode($data), MemberModel::CACHE_EXPIRE);
        }
        return $this->success($data);
    }

    /**
     * 清空用户缓存
     * @param $id
     * @throws Throwable
     */
    public function delCache($id){
        /** @var Redis $cache */
//        $cache = Di::getInstance()->get("REDIS");
        $cache = RedisPool::defer();
        $cache_key = "memberInfoAuth:" . $id;
        $cache->del($cache_key);
    }


    /**
     * 重置密码
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\Validate\Exception\Runtime
     */
    public function resetPassword($data){
        // 验证规则
        $rules = [
            'opassword'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
            'repassword'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
        ];

        // 验证字段的别名
        $alias = [
            'opassword'       => '旧密码',
            'password'    => '密码',
            'repassword'    => '确认密码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        if($data['password'] <> $data['repassword']){
            throw new ValidationException(ValidateEnums::CHECK_REQUIRED, '两次输入密码不一致');
        }
        $id = UserIdentityHelper::getId();
        /**读取用户信息,判断密码是否正确*/
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['opassword'], $member->salt)) {
            throw new DefaultException('旧密码错误！');
        }


        //初始化密码
        list($password, $salt) = self::getPassword($data['password']);

        //更新信息
        $userModel = new MemberModel();
        $res = $userModel->resetPassword($id, $password, $salt);

        if (!$res) {
            throw new DefaultException('更新密码失败！');
        }

        return $this->success(['id'=>$id]);
    }

    /**
     * 重置密码
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws Exception
     * @throws Throwable
     * @throws \EasySwoole\Mysqli\Exception\Exception
     * @throws \EasySwoole\Validate\Exception\Runtime
     */
    public function setPassword($data){
        // 验证规则
        $rules = [
            'id'    => 'required|notEmpty',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
        ];

        // 验证字段的别名
        $alias = [
            'id'       => '用户ID',
            'password'    => '密码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }

        $id = UserIdentityHelper::getId();
        if ($id != UserModel::SUPER_ADMIN ) {
            throw new DefaultException('无权修改该用户密码');
        }
        //初始化密码
        list($password, $salt) = self::getPassword($data['password']);

        //更新信息
        $userModel = new MemberModel();
        $res = $userModel->resetPassword($data['id'], $password, $salt);
        if (!$res) {
            throw new DefaultException('更新密码失败！');
        }

        return $this->success(['id'=>$data['id'], 'password'=>$data['password']]);
    }

    /**
     * 修改账户USDT editUsdt
     * @param $data
     * @return Output
     */
    public function editUsdt($data) : Output{
        // 验证规则
        $rules = [
            'usdt'    => 'required|notEmpty|lengthMin:6|lengthMax:50',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
        ];

        // 验证字段的别名
        $alias = [
            'usdt'       => 'USDT',
            'password'    => '密码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        $id = UserIdentityHelper::getId();
        /**读取用户信息,判断密码是否正确*/
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['password'], $member->salt)) {
            throw new DefaultException('密码错误！');
        }

        $data = [
            'usdt' => $data['usdt']
        ];
        MemberModel::create()->updateData($data, ['id' => $id]);

        return $this->success(['id'=>$id]);
    }

    /**
     * 修改账户币安地址 editBinance
     * @param $data
     * @return Output
     */
    public function editBinance($data) : Output{
        // 验证规则
        $rules = [
            'binance'    => 'required|notEmpty|lengthMin:6|lengthMax:250',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:200',
        ];

        // 验证字段的别名
        $alias = [
            'binance'       => '币安地址',
            'password'    => '密码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        $id = UserIdentityHelper::getId();
        /**读取用户信息,判断密码是否正确*/
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['password'], $member->salt)) {
            throw new DefaultException('密码错误！');
        }

        $data = [
            'binance' => $data['binance']
        ];
        MemberModel::create()->updateData($data, ['id' => $id]);

        return $this->success(['id'=>$id]);
    }

    /**
     * 修改账户波场地址 editTrx
     * @param $data
     * @return Output
     */
    public function editTrx($data) : Output{
        // 验证规则
        $rules = [
            'trx'    => 'required|notEmpty|lengthMin:6|lengthMax:250',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:200',
        ];

        // 验证字段的别名
        $alias = [
            'trx'       => '波场地址',
            'password'    => '密码',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        $id = UserIdentityHelper::getId();
        /**读取用户信息,判断密码是否正确*/
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['password'], $member->salt)) {
            throw new DefaultException('密码错误！');
        }

        $data = [
            'trx' => $data['trx']
        ];
        MemberModel::create()->updateData($data, ['id' => $id]);

        return $this->success(['id'=>$id]);
    }

    /**修改对公账户 */
    public function editPubBank($data) : Output{
        $rules = [
            'pub_bank_name' => 'required|notEmpty',
            'pub_bank_deposit' => 'required|notEmpty',
            'pub_bank_account_name' => 'required|notEmpty',
            'pub_bank_account_no' => 'required|notEmpty',
            'password'    => 'required|notEmpty|lengthMin:6|lengthMax:20',
        ];
        $alias = [
            'pub_bank_name' => '对公收款银行',
            'pub_bank_deposit' => '对公开户银行',
            'pub_bank_account_name' => '对公开户姓名',
            'pub_bank_account_no' => '对公银行帐号',
            'password'    => '密码',
        ];
        $validate = Validate::make($rules, [], $alias);
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        $id = UserIdentityHelper::getId();
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['password'], $member->salt)) {
            throw new DefaultException('密码错误！');
        }
        $data = [
            'pub_bank_name' => $data['pub_bank_name'],
            'pub_bank_deposit' => $data['pub_bank_deposit'],
            'pub_bank_account_name' => $data['pub_bank_account_name'],
            'pub_bank_account_no' => $data['pub_bank_account_no'],
        ];
        MemberModel::create()->updateData($data, ['id' => $id]);
        return $this->success(['id'=>$id]);
    }

    /**修改对私账户
     *`pri_bank_name` varchar(255) NOT NULL DEFAULT '' COMMENT '对私收款银行',
     * `pri_bank_deposit` varchar(255) NOT NULL DEFAULT '' COMMENT '对私开户银行',
     * `pri_bank_account_name` varchar(255) NOT NULL DEFAULT '' COMMENT '对私开户姓名',
     * `pri_bank_account_no` varchar(255) NOT NULL DEFAULT '' COMMENT '对私银行帐号',*/
    public function editPriBank($data) : Output
    {
        $rules    = [
            'pri_bank_name'         => 'required|notEmpty',
            'pri_bank_deposit'      => 'required|notEmpty',
            'pri_bank_account_name' => 'required|notEmpty',
            'pri_bank_account_no'   => 'required|notEmpty',
            'password'              => 'required|notEmpty|lengthMin:6|lengthMax:20',
        ];
        $alias    = [
            'pri_bank_name'         => '对私收款银行',
            'pri_bank_deposit'      => '对私开户银行',
            'pri_bank_account_name' => '对私开户姓名',
            'pri_bank_account_no'   => '对私银行帐号',
            'password'              => '密码',
        ];
        $validate = Validate::make($rules, [], $alias);
        $bool     = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        $id     = UserIdentityHelper::getId();
        $member = MemberModel::create()->get($id);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        if ($member->password <> CommonHelper::pwdEncrypt($data['password'], $member->salt)) {
            throw new DefaultException('密码错误！');
        }
        $data = [
            'pri_bank_name'         => $data['pri_bank_name'],
            'pri_bank_deposit'      => $data['pri_bank_deposit'],
            'pri_bank_account_name' => $data['pri_bank_account_name'],
            'pri_bank_account_no'   => $data['pri_bank_account_no'],
        ];
        MemberModel::create()->updateData($data, ['id' => $id]);
        return $this->success(['id' => $id]);
    }

    /**设置会员每单提成*/
    public function setProfit($data) : Output
    {
        $rules = [
            'profit' => 'required|notEmpty|between:0.01,' . OrderModel::MAXPROFIT,
            'user_id' => 'required|notEmpty',
        ];
        $alias = [
            'profit' => '每单提成',
            'user_id'  => '用户id',
        ];
        $validate = Validate::make($rules, [], $alias);
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        /**判断是否管理员登录,如果不是管理员那么判断当前用户是否是user_id的推荐人,如果不是那么抛出异常*/
        $member = MemberModel::create()->getOne(['id' => $data['user_id']]);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        $id = UserIdentityHelper::getId();
        if (UserIdentityHelper::getType() != UserModel::TYPE_INSIDE) {
            if ($member->referrer_id != $id) {
                throw new DefaultException('您不是该用户的推荐人，不能设置！');
            }
            /**判断设置的提成是否超过自己的提成*/
            $referrer = MemberModel::create()->getOne(['id' => $id]);
            if ($referrer->profit < $data['profit']) {
                throw new DefaultException('您设置的提成不能超过自己的提成['. $referrer->profit .']！');
            }
        }
        /**修改用户的每单提成*/
        $data = [
            'profit' => $data['profit'],
        ];
        MemberModel::create()->updateData($data, ['id' => $member->id]);
        return $this->success(['id' => $member->id]);
    }

    /**设置会员本金账户不可提现天数*/
    public function setlockedDay($data) : Output
    {
        $rules = [
            'locked_day' => 'required|notEmpty|between:0,' . OrderModel::MAXPLOCKEDDAY,
            'user_id' => 'required|notEmpty',
        ];
        $alias = [
            'locked_day' => '冻结天数',
            'user_id'  => '用户id',
        ];
        $validate = Validate::make($rules, [], $alias);
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }
        /**判断是否管理员登录,如果不是管理员那么判断当前用户是否是user_id的推荐人,如果不是那么抛出异常*/
        $member = MemberModel::create()->getOne(['id' => $data['user_id']]);
        if (!$member) {
            throw new DefaultException('用户不存在！');
        }
        $id = UserIdentityHelper::getId();
        if (UserIdentityHelper::getType() != UserModel::TYPE_INSIDE) {
            if ($member->referrer_id != $id) {
                throw new DefaultException('您不是该用户的推荐人，不能设置！');
            }
        }
        /**修改用户的每单提成*/
        $data = [
            'locked_day' => $data['locked_day'],
        ];
        MemberModel::create()->updateData($data, ['id' => $member->id]);
        return $this->success(['id' => $member->id]);
    }

    /**
     * 设置使用状态
     * @param $data
     * @return Output
     * @throws DefaultException
     * @throws \EasySwoole\Validate\Exception\Runtime
     */
    public function settingState($data) : Output
    {

        // 验证规则
        $rules = [
            'ids'   => 'required|notEmpty|isArray',
            'state' => 'required|notEmpty',
        ];

        // 验证字段的别名
        $alias = [
            'ids'   => '用户id',
            'state' => '设置类型',
        ];

        // 组装快速验证
        $validate = Validate::make($rules, [], $alias);

        //操作类型
        $validate->addColumn('state')->inArray([MemberModel::ENABLED, MemberModel::DISABLED]);

        // 验证结果
        $bool = $validate->validate($data);
        if (!$bool) {
            throw new DefaultException($validate->getError()->__toString());
        }

        $update = [
            'state' => $data['state'],
        ];

        $where = [
            'id' => [$data['ids'], 'in']
        ];

        $res = MemberModel::updateData($update, $where);

        foreach ($data['ids'] as $id) {
            self::delCache($id);
        }

        return $this->success(['affected_rows' => $res->lastQueryResult()->getAffectedRows()]);
    }

    /**
     * 获取用户利润
     * @param $id
     * @param int $profit
     * @return array|null
     */
    public function getProfit($id = null) {
        $id = $id ?? UserIdentityHelper::getId();
        // 查询数据库或其他数据源，根据ID获取对应的数据记录
        $record = MemberModel::getOne(['id' => $id]);

        // 判断是否存在记录
        if ($record) {
            return $this->success(['profit' => $record->profit]);
        } else {
            // 未找到记录
            throw new DefaultException('记录不存在');
        }
    }

    /**
     * 我推荐的会员
     * @param Request $request
     * @return Output
     * @throws Throwable
     * @throws \EasySwoole\Redis\Exception\RedisException
     */
    public function referrer(Request $request):Output
    {
        $params = $request->getQueryParams();
        /** @var Redis $cache */
        $cache     = Di::getInstance()->get("REDIS");
        $cache_key = "memberCache:myReferrer:" . json_encode($params + ['_id' => UserIdentityHelper::getId(), '_name' => UserIdentityHelper::getUsername()]);
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $data = json_decode($cache_data, true);
        } else {
            $params['referrer_id'] = UserIdentityHelper::getId();

            $form = new MemberListForm($params, $request);
            $data = $form->lists();
            $list = [];
            foreach ($data['list'] as $item) {
                $list[] = [
                    'id'                    => $item['id'],
                    'username'              => $item['username'],
                    'score'                 => $item['score'],
                    'profit'                => $item['profit'],
                    'created_at'            => date('Y-m-d', strtotime($item['created_at'])),
                    'referrer_profit'       => $item['referrer_profit'] ?? 0,
                    'referrer_profit_day'   => $item['referrer_profit_day'] ?? 0,
                    'referrer_profit_week'  => $item['referrer_profit_week'] ?? 0,
                    'referrer_profit_month' => $item['referrer_profit_month'] ?? 0,
                    'referrer_profit_year'  => $item['referrer_profit_year'] ?? 0,
                    'subordinate_count'     => $item['subordinate_count'] ?? 0,
                    'subordinate_score'     => $item['subordinate_score'] ?? 0,
                    'last_count_time'       => $item['last_count_time'],
                ];
            }
            $data['list'] = $list;
            $cache->set($cache_key, json_encode($data), MemberModel::CACHE_EXPIRE);
        }
        return $this->success($data);
    }


    /**
     * 递归找出用户所有推荐关系链 id referrer_id
     * @param $id
     * @param array $chain
     * @return array
     * @throws Exception
     */
    public function findAllRecommendedChain($id, $chain = [])
    {
        $user = MemberModel::getOne(['id' => $id]);
        if (empty($user)) {
            throw new Exception('用户不存在');
        }

        $chain[] = [
            'id'          => $user->id,
            'username'    => $user->username,
            'name'        => $user->name,
            'referrer_id' => $user->referrer_id,
            'phone'       => $user->phone,
            'state'       => $user->state,
            'profit'      => $user->profit
        ];
        if ($user->referrer_id > 0) {
            $chain = $this->findAllRecommendedChain($user->referrer_id, $chain);
        }

        return $chain;
    }

    /**找出用户推荐关系订单提成*/
    public function findAllRecommendedChainProfit($id)
    {
        /** @var Redis $cache */
        $cache     = Di::getInstance()->get("REDIS");
        $cache_key = "memberCache:findAllRecommendedChainProfit:" . $id;
        if ($cache_data = $cache->get($cache_key)) { //缓存存在
            $profits = json_decode($cache_data, true);
        } else {
            $profits = [];
            $chain = $this->findAllRecommendedChain($id);
            foreach ($chain as $item){
                /**取$profits最后一项*/
                $last_profit = end($profits);
                /**如果最后一项为空或者当前$item['profit'] >= $last_profit['profit'],
                 * 那么把当前$item添加到$profits中
                 * */
                if (empty($last_profit) || $item['profit'] >= $last_profit['profit']) {
                    $profits[] = [
                        'id'     => $item['id'],
                        'profit' => $item['profit']
                    ];
                }
            }
            /**缓存数据*/
            $cache->set($cache_key, json_encode($profits), MemberModel::CACHE_EXPIRE);
        }
        return $profits;
    }

    /**定时任务统计用户数据*/
    public function taskCountUserData()
    {
        /**每4个小时统计一次
         * last_count_time为null 或者小于4个小时前
         * 取出100条数据
         * */
//        $last_count_time = date("Y-m-d H:i:s", strtotime("-4 hour"));
        $last_count_time = date("Y-m-d H:i:s", time() - MemberModel::STATISTICS_INTERVAL);
        $sql = "SELECT * FROM ss_member WHERE is_delete=0 AND (last_count_time IS NULL OR last_count_time < '". $last_count_time ."') LIMIT 10";
        $queryBuild = new QueryBuilder();
        $queryBuild->raw($sql);
        $result = DbManager::getInstance()->query($queryBuild, true);
        if ($result->getResult()) {
            foreach ($result->getResult() as $item){
                /**@var CountUserHandler $eventCountUser*/
                \App\Process\LmtJob::getInstance()->createJob('eventCountUser', ["userId" => $item['id'], 'time' => time()]);
            }
        }
        return true;
    }

    /**统计用户数据*/
    public function countUserData($id)
    {
        /**6点前不执行,return false*/
        if(date('H')<6){
            return false;
        }
        if(!$user = MemberModel::getOne(['id' => $id])){
            return false;
        }
        if(strtotime($user['last_count_time']) > time() - MemberModel::STATISTICS_INTERVAL){
            return false;
        }
        /**今日个人收益today_user_profit*/
        $todayProfit = MemberProfitScoreModel::getOne(['user_id' => $id, 'type' => MemberProfitScoreModel::TYPE_USER_PROFIT, 'created_date' => date('Y-m-d')]);
        /**今日团队收益today_referrer_profit*/
        $referrerProfit = MemberProfitScoreModel::create()->where(['user_id' => $id, 'type' => MemberProfitScoreModel::TYPE_REFFERER_PROFIT, 'created_date' => date('Y-m-d')])->sum('score');
        /**订单统计*/
        $order = OrderService::getInstance()->unionCount($id);
        /**收益统计*/
        $profit = MemberProfitStatisticsService::getInstance()->statisticsByUser($id);
        /**下级账户余额统计*/
        list($countSubordinate, $subordinateScore) = $this->countSubordinate($id);

        $data = [
            'today_user_profit' => (!$todayProfit) ? 0 : $todayProfit['score'],
            'today_referrer_profit' => $referrerProfit ?? 0,
            'order_count' => $order['total_count'],
            'order_amount' => $order['total_order_amount'],
            'user_profit_count' => $profit['total_user_count'],
            'user_profit_amount' => $profit['total_user_amount'],
            'referrer_profit_count' => $profit['total_referrer_count'],
            'referrer_profit_amount' => $profit['total_referrer_amount'],
            'subordinate_count' => $countSubordinate,
            'subordinate_score' => $subordinateScore,
            'last_count_time' => date('Y-m-d H:i:s'),
        ];
        return MemberModel::updateData($data, ['id' => $id]);
    }

    /**下级账户余额统计*/
    public function countSubordinate($userId)
    {
        $count    = 0;
        $score    = 0;
        $children = (array)$userId;
        /**循环查询,最大递归深度User::MAX_SP_RECURSION_DEPTH*/
        for ($i = 0; $i < MemberModel::MAX_SP_RECURSION_DEPTH; $i++) {
            $res = MemberModel::makeQueryModel()->where(['referrer_id' => [$children, 'IN']])->all();
            if ($res->isEmpty()) {
                break;
            }
            $count += count($res);
            $score += array_sum(array_column($res->toArray(), 'score'));
            $children = array_column($res->toArray(), 'id');
        }
        return [$count, $score];
    }
    /**统计用户数量和积分*/
    public function countUserNumAndScore()
    {
        $query = MemberModel::getOne([], false, ['count(id) as count', 'sum(score) as score']);
        return [
            'count' => $query->count,
            'score' => $query->score
        ];
    }
/**as*/
    public function logList($params,$request){
        $column_cn_arr = [
            'id'              => 'id',
            'username'        => ['name' => '登陆用户'],
            'email'           => ['name' => '电子邮箱'],
            'name'            => ['name' => '姓名'],
            'phone'           => ['name' => '手机号'],
            'state'             => ['name' => '用户状态'],
            'avatar'          => ['name' => '头像'],
            'last_login_time' => ['name' => '最近登录时间'],
            'updated_by'      => ['name' => '更新操作员'],
            'created_by'      => ['name' => '创建人'],
        ];
        $form = new LogListForm($params, UserLogModel::class, $column_cn_arr, $request);
        return $form->lists();
    }
}
